package scala40rules;

import java.io.Serializable;
import java.util.ArrayList;
import javax.swing.ImageIcon;

public class CardSet implements Serializable {

	private static final long serialVersionUID = 1L;
	private ArrayList<Card> cardSet = new ArrayList<Card>();


	public CardSet(){
	}


	public CardSet(ArrayList<Card> card){
		this.cardSet=card;
	}


	public void addCard(Card card){
		this.cardSet.add(card);
	}


	public int size(){
		return this.cardSet.size();
	}


	public void setCard(int i, Card card){
		try{
			this.cardSet.set(i, card);
		}catch(Exception e){
			System.out.println("- Excepition- [CardSet || setCard()] Impossibile settare " +
					"la carta "+card.getSymbol()+" "+card.getSuit()+" all'index: "+i+
							" this.cardSet.size()="+this.cardSet.size());
		}
	}


	public Card getCard(int i){
//		try{
			return this.cardSet.get(i);
//		}catch(Exception e){
//			System.out.println("- Excepition- [CardSet || getCard()] Impossibile ottenere la carta da index: "+i+" this.cardSet.size()="+this.cardSet.size());
//			return new Card();
//		}
	}


	public void addCard(int i,Card card){
		try{
			this.cardSet.add(i, card);
		}catch(Exception e){
			System.out.println("- Excepition- [CardSet || addCard()] Impossibile aggiungere " +
					"la carta "+card.getSymbol()+" "+card.getSuit()+" all'index: "+i+
							" this.cardSet.size()="+this.cardSet.size());
		}
	}


	public Card removeCard(int i){
		try{
			return this.cardSet.remove(i);
		}catch(Exception e){
			System.out.println("- Excepition- [CardSet || removeCard()] Impossibile rimuovere carta da index: "+i);
			return new Card();
		}
	}


	public void addCardSet(CardSet cards){
		try{
			for(int i=0; i<cards.size(); i++ ){
				this.cardSet.add((cards.getCard(i)));
			}
		}catch(Exception e){
			System.out.println("- Excepition- [CardSet || addCardSet()] Impossibile aggiungere " +
					"le carte ");
		}
	}

//TODO controllare se viene usato e modificarlo con due for annidati
	public boolean equalCardSet(CardSet cs){
		if(cs.size() == this.size()){
			for(int i=0; i<this.size();i++){
				if( !this.getCard(i).equalCard(cs.getCard(i)) ){
					return false;
				}
			}
		}
		else{
			return false;
		}
		return true;
	}
	
	//metodo per modificare la posizione delle carte
	
	public boolean existKingAndAce(){
		int kingOrAceFound=0;
		for (int i=0; i<this.cardSet.size(); i++){
			if((this.cardSet.get(i).getOrdinalValue() == 1 ) ||
				(this.cardSet.get(i).getOrdinalValue() == 13 )){
				kingOrAceFound++;
			}
		}
		return (kingOrAceFound == 2);
	}


	public int getFirstJokerPosition(){
		for (int i=0; i<this.size(); i++){
//			System.out.println("                                      "+i);
//			System.out.println("      [CardSet || getFirstJokerPosition()] Carta: "+this.getCard(i).getSymbol());
			if(this.getCard(i).isJoker()){
				return i;
			}
		}
		return -1;
	}


	public int getFirstJokerWithoutSuitPosition(){
		for (int i=0; i<this.size(); i++){
//			System.out.println("                                      "+i);
//			System.out.println("      [CardSet || getFirstJokerPosition()] Carta: "+this.getCard(i).getSymbol());
			if(this.getCard(i).isJoker() && this.getCard(i).getSuit().equalsIgnoreCase(" ")){
				return i;
			}
		}
		return -1;
	}


	public boolean existJoker(){
		int jokerFound=0;
		for (int i=0; i<this.size(); i++){
			if(this.getCard(i).getOrdinalValue() == 14 ){
				jokerFound++;
			}
		}
//		System.out.println("[CardSet || existJoker()] jokerFound "+jokerFound);
		return (jokerFound > 0);
	}


    public boolean existNotSuitedJoker(){
		for (int i=0; i<this.size(); i++){
			if(this.getCard(i).getOrdinalValue() == 14 && this.getCard(i).getSuit().equals(" ")){
				return true;
			}
		}
		return false;
	}

	 
	public boolean existJoker(Tris tris){
		int jokerFound=0;
		System.out.println("[CardSet || existJoker(CardSet cs)] cs.size()"+tris.size());
		for (int i=0; i<tris.size(); i++){
			System.out.println("                                      "+i);
			
			System.out.println("      [CardSet || existJoker(CardSet cs)] Carta: "+tris.getCard(i).getSymbol());
			if(tris.getCard(i).getOrdinalValue() == 14 ){
				jokerFound++;
			}
		}
		System.out.println("[CardSet || existJoker()] jokerFound "+jokerFound);
		return (jokerFound > 0);
	}


	public boolean isValidSet(){
        if(this.size()==0){
            return false;
        }
		Tris myTris = new Tris(this);
		Quatris myQuatris=new Quatris(this);
		Scale myScale=new Scale(this);
//		System.out.println("[CardSet || isValidSet()] myTris.isValidTris() " + myTris.isValidTris());
//		System.out.println("[CardSet || isValidSet()] myQuatris.isValidQuatris() " + myQuatris.isValidQuatris());
//		System.out.println("[CardSet || isValidSet()] myScale.isValidScale() " +myScale.isValidScale());
		
        //siccome compilatore fannullone, ottimizziamo a manina...
        if(myTris.isValidTris()){return true;}
        if(myQuatris.isValidQuatris()){return true;}
        if(myScale.isValidScale()){return true;}
		return false;
	}


	public boolean mustChooseJokerValue(){	
		Tris myTris = new Tris(this);
		Quatris myQuatris = new Quatris(this);
		//System.out.println(" TRIS VALIDO="+myTris.isValidTris()+"  existJoker="+myTris.existJoker());
		return ( ( myTris.isValidTris() && myTris.existJokerWithoutSuit()) ||
				( myQuatris.isValidQuatris() && myQuatris.existJokerWithoutSuit()));
	}
	
	public boolean mustSetJokerSuitAtQuatris(){
		Quatris myQuatris = new Quatris(this);
		
		return ( myQuatris.isValidQuatris() && myQuatris.existJokerWithoutSuit());
	}
	
	public void setJokerSuitAtQuatris(){
		Quatris myQuatris = new Quatris(this);
		CardSet jokers = this.getPossibleJokerValue();
		
		for(int i=0; i<jokers.size(); i++){
			int position = myQuatris.getFirstJokerWithoutSuitPosition();
			myQuatris.setCard(getFirstJokerPosition(), jokers.getCard(i));
		}
		
	}


	public CardSet getPossibleJokerValue(){
		CardSet result = new CardSet();
		result.addCard(new Card(14, "Joker", "hearts",true, "src/cards/joker-hearts.png","src/small_cards/joker-hearts.png"));
		result.addCard(new Card(14, "Joker", "clubs",true, "src/cards/joker-clubs.png","src/small_cards/joker-clubs.png"));
		result.addCard(new Card(14, "Joker", "diamonds",true, "src/cards/joker-diamonds.png","src/small_cards/joker-diamonds.png"));
		result.addCard(new Card(14, "Joker", "spades",true, "src/cards/joker-spades.png","src/small_cards/joker-spades.png"));

        //in teoria si puo' fare a meno di queste due righe
		CardSet temp = new CardSet();
        temp.addCardSet(this);

		for(int i=0; i<temp.size(); i++){
			if(!temp.getCard(i).isJokerWithoutSuit()){
				for(int j=0; j<result.size();j++){
					if(temp.getCard(i).getSuit().equalsIgnoreCase(result.getCard(j).getSuit())){
						result.removeCard(j);
					}
				}
			}
		}
		return result;
		
		//TODO FARE LO STESSO PER IL QUATRIS
		
	}


	public void resetJoker(){
		for(int j=0; j<this.size();j++){
			if(this.getCard(j).isJoker()){
				this.removeCard(j);
				this.addCard(j, new Card(14, "Joker", " ",true, "src/cards/joker.png","src/small_cards/joker.png"));
			}
		}
	}
	

    public CardSet addCardToValidSet(Card card){

		Tris myTris = new Tris(this);
		if((myTris.tryToAdd(card)!=null)){
			return myTris.tryToAdd(card);
		}

//      al quatris nn si puo' aggiungere niente, quindi inutile fare il test
//		Quatris myQuatris=new Quatris(this);
//		if(myQuatris.isValidQuatris()){
//			return null;
//		}

		Scale myScale=new Scale(this);
		if(myScale.isValidScale()){
			return myScale.tryToAdd(card);
		}

		return null;
	}


    public CardSet replaceJokerInValidSet(Card card){

		if (this.existJoker()){
			Tris myTris = new Tris(this);
			if(myTris.isValidTris()){
				return myTris.tryToSubstitute(card);
			}

			Quatris myQuatris=new Quatris(this);
			if(myQuatris.isValidQuatris()){
				return myQuatris.tryToSubstitute(card);
			}

			Scale myScale=new Scale(this);
			if(myScale.isValidScale()){
				return myScale.tryToSubstitute(card);
			}
		}

		return null;
	}

    //DISMESSO in teoria
	public CardSet checkReplaceAndAdd(Card card){
		
		if (this.existJoker()){
			Tris myTris = new Tris(this);
			if(myTris.isValidTris()){
				return myTris.tryToSubstitute(card);
			}
			
			Quatris myQuatris=new Quatris(this);
			if(myQuatris.isValidQuatris()){
				return myQuatris.tryToSubstitute(card);
			}
			
			Scale myScale=new Scale(this);
			if(myScale.isValidScale()){
				return myScale.tryToSubstitute(card);
			}
		}
		
		System.out.println(" THIS.SIZE "+this.size());
		Tris myTris = new Tris(this);
			System.out.println(" ARRIVO FINO a qui A");
		if((myTris.tryToAdd(card)!=null)){
			System.out.println(" ARRIVO FINO a qui 1 ");
			return myTris.tryToAdd(card);
		}
		
		System.out.println(" THIS.SIZE "+this.size());
		Quatris myQuatris=new Quatris(this);
		System.out.println(" ARRIVO FINO a qui 3");
		if(myQuatris.isValidQuatris()){
			return null;
		}
		
		Scale myScale=new Scale(this);
		if(myScale.isValidScale()){
			return myScale.tryToAdd(card);
		}
				
		return null;
	}
	
	
	public int sumNotValidCardsetValue(){
		int result=0;
		int j;
		
		//se cardset non e' un validSet
		for (int i=0; i<this.cardSet.size(); i++){
			j = this.getCard(i).getOrdinalValue();
			switch(j){
			case 1: result+= 11; break;
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
			case 9:
			case 10: result+= j; break;
			case 11:
			case 12:
			case 13: result+= 10; break;
			case 14: result+= 25; break;
			default: result+= 1000;
			}
		}
		return result;
		
	}


	public int sumValidCardsetValue(){
		int result=6000;
		int j;

		//se cardset e' un Tris
		try{
			Tris myTris = new Tris(this);
			if(myTris.isValidTris()){
				return myTris.sumTrisValue();
			}
		}catch(Exception e){System.out.println("[sumCardsetValue] il Cardset non e' un Tris");};

		//se cardset e' un Quatris
		try{
			Quatris myQuatris = new Quatris(this);
			if(myQuatris.isValidQuatris()){
				return myQuatris.sumQuatrisValue();
			}
		}catch(Exception e){System.out.println("[sumCardsetValue] il Cardset non e' un Quatris");};

		//se cardset e' una Scale
		try{
			Scale myScale = new Scale(this);
			System.out.println("[CardSet] myScale e' di dimensione: "+myScale.size());
			if(myScale.isValidScale()){
				return myScale.sumScaleValue();
			}
		}catch(Exception e){System.out.println("[sumCardsetValue] il Cardset non e' una Scale");};

        System.out.println("[CardSet || sumValidCardset] scoperto che non era un validCardset, ritorniamo il risultato di sumNotValidCardset()");
		return this.sumNotValidCardsetValue();
	}


    public String getSpaces(int lenght){
        String s="";
        for (int i=0; i<lenght; i++){
            s+=" ";
        }
        return s;
    }


    public void printCardset(){
        this.printCardset("NESSUN TITOLO");
    }


    public void printCardset(String titolo){
        int symbolLenght = 8;
        int suitLenght = 8;
        int valueLenght = 7;
        System.out.println("\n\n"+titolo);
        System.out.println("[ SYMBOL |  SUIT  | VALUE ]");
        System.out.println("---------------------------");
        for(int i=0; i<this.cardSet.size(); i++){
            System.out.print("[");
            System.out.print(getSpaces((symbolLenght - this.cardSet.get(i).getSymbol().length())/2));
            System.out.print(this.cardSet.get(i).getSymbol());
            System.out.print(getSpaces((symbolLenght - this.cardSet.get(i).getSymbol().length())/2 + (symbolLenght - this.cardSet.get(i).getSymbol().length())%2));
            System.out.print("|");
            System.out.print(getSpaces((suitLenght - this.cardSet.get(i).getSuit().length())/2));
            System.out.print(this.cardSet.get(i).getSuit());
            System.out.print(getSpaces((suitLenght - this.cardSet.get(i).getSuit().length())/2 + (suitLenght - this.cardSet.get(i).getSuit().length())%2));
            System.out.print("|");
            System.out.print(getSpaces((valueLenght - Integer.toString(this.cardSet.get(i).getOrdinalValue()).length())/2));
            System.out.print(this.cardSet.get(i).getOrdinalValue());
            System.out.print(getSpaces((valueLenght - Integer.toString(this.cardSet.get(i).getOrdinalValue()).length())/2 + (valueLenght - Integer.toString(this.cardSet.get(i).getOrdinalValue()).length())%2));
            System.out.println("]");
        }
        System.out.println("\n");
    }

}
